// Autodiscover.cs
//
// This file contains a proxy Autodiscover class.
//
// Copyright (C) 2007 Microsoft Corporation. All rights reserved.
//

namespace ConferenceRoomSchedule
{
	/// <summary>
	/// Proxy class to Exchange Autodiscover service
	/// </summary>

	public class Autodiscover
	{
		// Guid for SCP URL keyword
		private const string ScpUrlGuidString = @"77378F46-2C66-4aa9-A6A6-3E7A48B19596";

		// Guid for SCP pointer keyword
		private const string ScpPtrGuidString = @"67661d7F-8FC4-4fa7-BFAC-E1D7794C1F68";

		// Autodiscover path
		private const string AutodiscoverPath = @"/autodiscover/autodiscover.xml";

		// Enable verbose Console Tracing for debug build
#if DEBUG
		private const bool TraceToConsole = true;
#else
        private const bool TraceToConsole = false;
#endif

		/// <summary>
		/// Autodiscover the configurations for a specific e-mail address.
		/// </summary>
		/// <param name="emailAddress">SMTP address</param>
		/// <param name="nc">Network credentials, if null, then current credentials are used</param>
		/// <param name="maxHops">Maximum number of Active Directory and e-mail address redirections</param>
		/// <param name="allowSelfSignedCerts">Allow self-signed certificates flag</param>
		/// <returns>Autodiscover response</returns>
		/// 
		public static AutodiscoverResponseXml Discover(
		   string emailAddress,
		   System.Net.NetworkCredential nc,
		   ref int maxHops,
		   bool allowSelfSignedCerts)
		{
			CheckAndDecrementHops(ref maxHops);
            System.Collections.Generic.List<string> urls = new System.Collections.Generic.List<string>();

			// Verify parameters.
			if (emailAddress == null)
			{
				throw new System.ArgumentNullException("E-mail address should not be null");
			}

			string[] emailAddressParts = emailAddress.Split('@');

			if ((emailAddressParts.Length < 2) || (string.IsNullOrEmpty(emailAddressParts[1])))
			{
				throw new System.ArgumentException("Invalid format for e-mail address: domain is not specified");
			}

			// Get the domain from the e-mail address.
			string domainName = emailAddressParts[1];

			// Get either a list of SCP URLs or a list with 0 entries.
		//	System.Collections.Generic.List<string> urls = GetScpUrlList(domainName, null, ref maxHops);

			// Create the Autodiscover response.
			AutodiscoverResponseXml autodiscoverResponse = null;

			// Try SCP URLs retrieved from Active Directory to make Autodiscover requests.
            //if (urls.Count > 0)
            //{
            //    // Get the Autodiscover response with client configuration information.
            //    autodiscoverResponse = DiscoverTryUrls(
            //       emailAddress,
            //       nc,
            //       urls,
            //       true,
            //       allowSelfSignedCerts,
            //       ref maxHops);

            //    // If a valid Outlook response is returned, stop the search.
            //    if (IsOutlookDataReturned(autodiscoverResponse))
            //    {
            //        return autodiscoverResponse;
            //    }
            //    else
            //    {
            //        // Clear the list of URLs to try two default URLs.
            //        urls.Clear();
            //    }
            //}

			// Add two SSL URLs built from the domain part of SMTP address.
			urls.Add("https://" + domainName + AutodiscoverPath);
			urls.Add("https://autodiscover." + domainName + AutodiscoverPath);

			ConsoleTrace("\n-- No response returned from SCP URLs, trying default URLs:");
			ConsoleTrace("+=  'https://" + domainName + AutodiscoverPath + "'");
			ConsoleTrace("+=  'https://autodiscover." + domainName + AutodiscoverPath + "'");

			// Try two SSL URLs.
			autodiscoverResponse = DiscoverTryUrls(
			   emailAddress,
			   nc,
			   urls,
			   false,
			   allowSelfSignedCerts,
			   ref maxHops);

			// If no response is returned yet
			if (!IsOutlookDataReturned(autodiscoverResponse))
			{
				// Try non-SSL URL to get SSL redirect URL.
				string redirectUrl = GetRedirectUrl(domainName);

				// If returned redirectUrl is not null it is a valid redirect SSL URL.
				// Then attempt to request Autodiscover data.
				if (!string.IsNullOrEmpty(redirectUrl))
				{
					urls.Clear();
					urls.Add(redirectUrl);

					autodiscoverResponse = DiscoverTryUrls(
					   emailAddress,
					   nc,
					   urls,
					   false,
					   allowSelfSignedCerts,
					   ref maxHops);
				}
			}

			return autodiscoverResponse;
		}
		

		/// <summary>
		/// Autodiscover e-mail address against a list of URLs.
		/// </summary>
		/// <param name="emailAddress">SMTP address</param>
		/// <param name="nc">Network credentials</param>
		/// <param name="urls">List of URLs to try</param>
		/// <param name="authoritative">URLs are from Active Directory</param>
		/// <param name="allowSelfSignedCerts">Allow self signed certs flag</param>
		/// <param name="maxHops">The number of remaining Active Directory or e-mail address redirections</param>
		/// <returns></returns>

		private static AutodiscoverResponseXml DiscoverTryUrls(
		   string emailAddress,
		   System.Net.NetworkCredential nc,
		   System.Collections.Generic.List<string> urls,
		   bool authoritative,
		   bool allowSelfSignedCerts,
		   ref int maxHops)
		{
			AutodiscoverResponseXml responseXml = null;

			foreach (string url in urls)
			{
				// Try each URL - send request to Autodiscover and parse the response.
				responseXml = DiscoverTryUrl(emailAddress, nc, url, authoritative, allowSelfSignedCerts);

				// Check if the response contains data.
				if ((IsOutlookDataReturned(responseXml) && (responseXml.OutlookData.Account != null)))
				{
					// Check if the response contains a redirect.
					if (responseXml.OutlookData.Account.Action == "redirectAddr")
					{
						// Retry Autodiscover with new redirect e-mail address.
						string redirectEmailAddress = responseXml.OutlookData.Account.RedirectAddr;
						ConsoleTrace("== Redirect EmailAddress='" + redirectEmailAddress + "' is returned, restarting the search");
						responseXml = Discover(redirectEmailAddress, nc, ref maxHops, allowSelfSignedCerts);
					}

					// Outlook account data is returned by the Autodiscover service - stop the search.
					break;
				}

				// Check for error response.
				else
				{
					if (IsErrorResponseReturned(responseXml))
					{
						ConsoleTrace("-! ErrorCode='" + responseXml.ErrorResponse.Error.ErrorCode +
						   "', Message='" + responseXml.ErrorResponse.Error.Message + "' is returned by Audiscover service");
					}
				}
			}

			// Return the successful response.
			return responseXml;
		}

		/// <summary>
		/// Contact Autodiscover service at the given URL with the given e-mail address.
		/// </summary>
		/// <param name="emailAddress">SMTP address</param>
		/// <param name="nc">Network credentials</param>
		/// <param name="url">A single URL to try</param>
		/// <param name="authoritative">URL is from Active Directory</param>
		/// <param name="allowSelfSignedCerts">Allow self-signed certificates</param>
		/// <returns></returns>

		private static AutodiscoverResponseXml DiscoverTryUrl(
		   string emailAddress,
		   System.Net.NetworkCredential nc,
		   string url,
		   bool authoritative,
		   bool allowSelfSignedCerts)
		{
			AutodiscoverResponseXml responseXml = null;
			ConsoleTrace("\n=? Trying '" + emailAddress + "' at '" + url + "'");
			try
			{
				// Custom handling of certificates.
				if (allowSelfSignedCerts)
				{
					// Set the callback to handle certificates.
					System.Net.ServicePointManager.ServerCertificateValidationCallback += CertificateValidationCallBack;
				}

				// Create WebRequest based on credentials and URL.
				System.Net.WebRequest webRequest = System.Net.HttpWebRequest.Create(url);
				if (nc == null)
					webRequest.UseDefaultCredentials = true;
				else
					webRequest.Credentials = nc;

				// Create Autodiscover request body to POST to Autodiscover service.
				webRequest.Method = "POST";
				webRequest.ContentType = "text/xml";

				System.IO.Stream webRequestStream = webRequest.GetRequestStream();
				SerializeRequest(emailAddress, webRequestStream);
				webRequestStream.Close();

				// Create WebResponse.
				System.Net.WebResponse webResponse;


				// Send the Autodiscover request, get the response.
				webResponse = webRequest.GetResponse();

				// Deserialize and get the Autodiscover response.
				responseXml = DeserializeResponse(webResponse.GetResponseStream());
			}

			catch (System.Net.WebException e)
			{
				if (authoritative)
					ConsoleTrace("!! Error: " + e.ToString());
				else
					ConsoleTrace("-! Info: " + e.ToString());
			}
			finally
			{
				if (allowSelfSignedCerts)
				{
					// Remove the callback.
					System.Net.ServicePointManager.ServerCertificateValidationCallback -= CertificateValidationCallBack;
				}
			}

			// Return the Autodiscover response.
			return responseXml;
		}

		/// <summary>
		/// Get redirection to SSL Autodiscover URL from non-SSL URL.
		/// </summary>
		/// <param name="emailAddress">SMTP address</param>
		/// <param name="nc">Network credentials</param>
		/// <param name="url">A single URL to try</param>
		/// <param name="authoritative">URL is from Active Directory</param>
		/// <returns>Valid redirect SSL URL or null</returns>

		private static string GetRedirectUrl(string domainName)
		{
			string url = "http://autodiscover." + domainName + AutodiscoverPath;

			ConsoleTrace("\n?? Trying GET redirect URL on non-SSL URL '" + url + "'");

			try
			{
				// Create the HTTP Web request.
				System.Net.HttpWebRequest httpRequest = (System.Net.HttpWebRequest)System.Net.HttpWebRequest.Create(url);

				httpRequest.Method = "GET";
				httpRequest.AuthenticationLevel = System.Net.Security.AuthenticationLevel.None;
				httpRequest.ImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Anonymous;
				httpRequest.AllowAutoRedirect = false;
				httpRequest.PreAuthenticate = false;

				// Send the request and get the response.
				System.Net.HttpWebResponse httpResponse = (System.Net.HttpWebResponse)httpRequest.GetResponse();

				// Check if 301 or 302 codes are returned.
				if ((httpResponse.StatusCode == System.Net.HttpStatusCode.Moved) ||
				   (httpResponse.StatusCode == System.Net.HttpStatusCode.Redirect))
				{
					// Get the redirect URL and verify that it's valid.
					string redirectUrl = httpResponse.Headers["Location"];
					bool isValidRedirectUrl = false;

					if (!string.IsNullOrEmpty(redirectUrl))
					{
						System.UriBuilder urib = new System.UriBuilder(redirectUrl);

						// Check if URI is SSL and that the path matches.
						isValidRedirectUrl =
						   (string.Compare(urib.Scheme, "https", true) == 0) &&
						   (string.Compare(urib.Path, AutodiscoverPath, true) == 0);
					}

					// Return the redirect URL.
					if (isValidRedirectUrl)
					{
						ConsoleTrace("+= '" + url + "' returns valid redirect url '" + redirectUrl + "'");
						return redirectUrl;
					}
					else
					{
						ConsoleTrace("-! '" + url + "' returns invalid redirect url '" + redirectUrl + "'");
					}
				}

				// The default non-SSL end point has not been setup to redirect.
				else
				{
					ConsoleTrace("-! '" + url + "' is not configured for redirection");
				}
			}

			catch (System.Net.WebException e)
			{
				ConsoleTrace("!! Exception: " + e.ToString());
			}

			// No redirect URL available or it is invalid.
			return null;
		}

		/// <summary>
		/// Callback to handle SSL certificate.
		/// </summary>
		/// <param name="sender">Sender</param>
		/// <param name="certificate">Certificate</param>
		/// <param name="chain">Chain</param>
		/// <param name="sslPolicyErrors">SSL policy errors</param>
		/// <returns>true if certificate is OK</returns>
		private static bool CertificateValidationCallBack(
			  object sender,
			  System.Security.Cryptography.X509Certificates.X509Certificate certificate,
			  System.Security.Cryptography.X509Certificates.X509Chain chain,
			  System.Net.Security.SslPolicyErrors sslPolicyErrors)
		{
			// If no errors - exit.
			if (sslPolicyErrors == System.Net.Security.SslPolicyErrors.None)
			{
				return true;
			}

			// If RemoteCertificateChainErrors, walk the chain to handle errors.
			if ((sslPolicyErrors & System.Net.Security.SslPolicyErrors.RemoteCertificateChainErrors) != 0)
			{
				if (chain != null && chain.ChainStatus != null)
				{
					foreach (System.Security.Cryptography.X509Certificates.X509ChainStatus status in chain.ChainStatus)
					{
						if ((certificate.Subject == certificate.Issuer) &&
						   (status.Status == System.Security.Cryptography.X509Certificates.X509ChainStatusFlags.UntrustedRoot))
						{
							// Untrusted root for self-signed certificate is OK.
							continue;
						}
						else
						{
							if (status.Status != System.Security.Cryptography.X509Certificates.X509ChainStatusFlags.NoError)
							{
								ConsoleTrace("!! Chain Error status='" + status.Status.ToString() +
										  "', statusInformation='" + status.StatusInformation + "'");
								// Fail on any other certificate error.
								return false;
							}
						}
					}
				}

				// No errors except untrusted root for self-signed certificates.
				return true;
			}
			else
			{
				return false;
			}
		}

		/// <summary>
		/// Case insensitive check if the collection contains the string.
		/// </summary>
		/// <param name="collection">The collection of objects, only strings are checked</param>
		/// <param name="match">String to match</param>
		/// <returns>true, if match contains in the collection</returns>
		private static bool Contains(System.Collections.ICollection collection, string match)
		{
			foreach (object obj in collection)
			{
				string str = obj as string;
				if (str != null)
				{
					if (string.Compare(str, match, true) == 0)
					{
						return true;
					}
				}
			}
			return false;
		}

		/// <summary>
		/// Check maxHops, if less than one - throw exception, otherwise - decrement the counter.
		/// </summary>
		/// <param name="maxHops">Hops counter</param>
		private static void CheckAndDecrementHops(ref int maxHops)
		{
			if (maxHops <= 0)
			{
				ConsoleTrace("!! The number of hops exceeded the limit");
				throw new System.ArgumentOutOfRangeException("maxHops", "The number of hops exceeded the limit");
			}
			maxHops = maxHops - 1;
		}

		/// <summary>
		/// Check if AutodiscoverResponse contains Outlook data.
		/// </summary>
		/// <param name="autodiscoverResponse">Autodiscover response to verify</param>
		/// <returns>true if OutlookDate is presented</returns>

		private static bool IsOutlookDataReturned(AutodiscoverResponseXml autodiscoverResponse)
		{
			return ((autodiscoverResponse != null) &&
				  (autodiscoverResponse.OutlookData != null));
		}

		/// <summary>
		/// Check if AutodiscoverResponse contains Error data.
		/// </summary>
		/// <param name="autodiscoverResponse">Autodiscover response to verify</param>
		/// <returns>true if ErrorResponse is presented</returns>

		private static bool IsErrorResponseReturned(AutodiscoverResponseXml autodiscoverResponse)
		{
			return ((autodiscoverResponse != null) &&
				  (autodiscoverResponse.ErrorResponse != null));
		}

		/// <summary>
		/// Console Tracing function.
		/// </summary>
		/// <param name="message">Message to output to Console</param>
		private static void ConsoleTrace(string message)
		{
			if (TraceToConsole)
				System.Console.WriteLine(message);
		}

		/// <summary>
		/// Generate an AutoDiscover XML Request.
		/// </summary>
		/// <param name="emailAddress">E-mail address to Autodiscover</param>
		/// <param name="requestStream">Output stream for serialized Autodiscover request</param>
		private static void SerializeRequest(string emailAddress, System.IO.Stream requestStream)
		{
			AutodiscoverRequestXml requestXml =
			   AutodiscoverRequestXml.NewRequest(emailAddress);

			System.Xml.Serialization.XmlSerializer xmlSerializer =
			   new System.Xml.Serialization.XmlSerializer(typeof(AutodiscoverRequestXml));

			xmlSerializer.Serialize(requestStream, requestXml);
		}

		/// <summary>
		/// Parse an AutoDiscover XML Response.
		/// </summary>
		/// <param name="responseStream">Stream to deserialize</param>
		/// <returns>Deserialized AutodiscoverResponse class instance</returns>

		private static AutodiscoverResponseXml DeserializeResponse(System.IO.Stream responseStream)
		{
			System.Xml.Serialization.XmlSerializer xmlDeserializer =
			   new System.Xml.Serialization.XmlSerializer(typeof(AutodiscoverResponseXml));

			return xmlDeserializer.Deserialize(responseStream) as AutodiscoverResponseXml;
		}

		#region Autodiscover Request Xml

		const string OutlookRequestNamespace = "http://schemas.microsoft.com/exchange/autodiscover/outlook/requestschema/2006";
		const string OutlookResponseNamespace = "http://schemas.microsoft.com/exchange/autodiscover/outlook/responseschema/2006a";
		const string AutodiscoverResponseNamespace = "http://schemas.microsoft.com/exchange/autodiscover/responseschema/2006";

		/*   Autodiscover Request Xml sample
		  
		  <Autodiscover xmlns="http://schemas.microsoft.com/exchange/autodiscover/outlook/requestschema/2006">
			<Request>
			  <EMailAddress>user@contoso.com</EMailAddress>
			  <AcceptableResponseSchema>http://schemas.microsoft.com/exchange/autodiscover/outlook/responseschema/2006a</AcceptableResponseSchema>
			</Request>
		  </Autodiscover>

		 */

		/// <summary></summary>
		[System.Xml.Serialization.XmlRoot(ElementName = "Autodiscover", Namespace = OutlookRequestNamespace)]
		public class AutodiscoverRequestXml
		{
			/// <summary></summary>
			[System.Xml.Serialization.XmlElement(IsNullable = false)]
			public RequestXml Request = null;

			/// <summary>Creates Autodiscover XML request</summary>
			public static AutodiscoverRequestXml NewRequest(string address)
			{
				RequestXml request = new RequestXml();
				request.EMailAddress = address;
				request.AcceptableResponseSchema = OutlookResponseNamespace;

				AutodiscoverRequestXml outlookRequest = new AutodiscoverRequestXml();
				outlookRequest.Request = request;

				return outlookRequest;
			}
		}

		/// <summary>Request container</summary>
		[System.Xml.Serialization.XmlRoot(ElementName = "Request", Namespace = OutlookRequestNamespace)]
		public class RequestXml
		{
			/// <summary>User SMTP address</summary>
			public string EMailAddress = null;

			/// <summary>The response schema, acceptable for a client</summary>
			public string AcceptableResponseSchema = null;
		}

		#endregion

		#region Autodiscover Response Xml

		/* Autodiscover sample response

		<Autodiscover xmlns="http://schemas.microsoft.com/exchange/autodiscover/responseschema/2006">
			<Response xmlns="http://schemas.microsoft.com/exchange/autodiscover/outlook/responseschema/2006a">
				<User>
					<DisplayName>First Last</DisplayName>
					<LegacyDN>/o=contoso/ou=First Administrative Group/cn=Recipients/cn=iuser885646</LegacyDN>
					<DeploymentId>644560b8-a1ce-429c-8ace-23395843f701</DeploymentId>
				</User>
				<Account>
					<AccountType>email</AccountType>
					<Action>settings</Action>
					<Protocol>
						<Type>EXCH</Type>
						<Server>MBX-SERVER.mail.internal.contoso.com</Server>
						<ServerDN>/o=contoso/ou=Exchange Administrative Group (FYDIBOHF23SPDLT)/cn=Configuration/cn=Servers/cn=MBX-SERVER</ServerDN>
						<ServerVersion>72008287</ServerVersion>
						<MdbDN>/o=contoso/ou=Exchange Administrative Group (FYDIBOHF23SPDLT)/cn=Configuration/cn=Servers/cn=MBX-SERVER/cn=Microsoft Private MDB</MdbDN>
						<ASUrl>https://mail.contoso.com/ews/exchange.asmx</ASUrl>
						<OOFUrl>https://mail.contoso.com/ews/exchange.asmx</OOFUrl>
						<UMUrl>https://mail.contoso.com/unifiedmessaging/service.asmx</UMUrl>
						<OABUrl>https://mail.contoso.com/OAB/d29844a9-724e-468c-8820-0f7b345b767b/</OABUrl>
					</Protocol>
					<Protocol>
						<Type>EXPR</Type>
						<Server>Exchange.contoso.com</Server>
						<ASUrl>https://mail.contoso.com/ews/exchange.asmx</ASUrl>
						<OOFUrl>https://mail.contoso.com/ews/exchange.asmx</OOFUrl>
						<UMUrl>https://mail.contoso.com/unifiedmessaging/service.asmx</UMUrl>
						<OABUrl>https://mail.contoso.com/OAB/d29844a9-724e-468c-8820-0f7b345b767b/</OABUrl>
					</Protocol>
					<Protocol>
						<Type>WEB</Type>
						<Internal>
							<OWAUrl AuthenticationMethod="Ntlm, WindowsIntegrated">https://cas-01-server.mail.internal.contoso.com/owa</OWAUrl>
							<OWAUrl AuthenticationMethod="Ntlm, WindowsIntegrated">https://cas-02-server.mail.internal.contoso.com/owa</OWAUrl>
							<OWAUrl AuthenticationMethod="Basic">https://cas-04-server.mail.internal.contoso.com/owa</OWAUrl>
							<OWAUrl AuthenticationMethod="Ntlm, WindowsIntegrated">https://cas-05-server.mail.internal.contoso.com/owa</OWAUrl>
						</Internal>
					</Protocol>
				</Account>
			</Response>
		</Autodiscover>
		*/

		/// <summary>Autodiscover response container</summary>
		[System.Xml.Serialization.XmlRoot(ElementName = "Autodiscover", Namespace = AutodiscoverResponseNamespace)]
		public class AutodiscoverResponseXml
		{
			/// <summary>Outlook data container</summary>
			[System.Xml.Serialization.XmlElement(IsNullable = false, ElementName = "Response", Namespace = OutlookResponseNamespace)]
			public OutlookDataXml OutlookData = null;

			/// <summary>Error response</summary>
			[System.Xml.Serialization.XmlElement(IsNullable = false, ElementName = "Response", Namespace = AutodiscoverResponseNamespace)]
			public ErrorResponseXml ErrorResponse = null;
		}

		/// <summary>Outlook data response container</summary>
		[System.Xml.Serialization.XmlRoot(ElementName = "Response", Namespace = OutlookResponseNamespace)]
		public class OutlookDataXml
		{
			/// <summary>User data container</summary>
			public UserXml User = null;
			/// <summary>Account data container</summary>
			public AccountXml Account = null;
		}

		/// <summary>User container</summary>
		[System.Xml.Serialization.XmlRoot(ElementName = "User", Namespace = OutlookResponseNamespace)]
		public class UserXml
		{
			/// <summary>User display name</summary>
			public string DisplayName = null;
			/// <summary>Exchange LegacyDN address</summary>
			public string LegacyDN = null;
			/// <summary>Deployment Id</summary>
			public string DeploymentId = null;
		}

		/// <summary>Account container</summary>
		[System.Xml.Serialization.XmlRoot(ElementName = "Account", Namespace = OutlookResponseNamespace)]
		public class AccountXml
		{
			/// <summary></summary>
			public string AccountType = null;
			/// <summary></summary>
			public string Action = null;
			/// <summary></summary>
			public string RedirectAddr = null;
			/// <summary></summary>
			[System.Xml.Serialization.XmlElement]
			public ProtocolXml[] Protocol = null;
			/// <summary></summary>
			public string SSL = null;
			/// <summary></summary>
			public string AuthPackage = null;
		}

		/// <summary>Protocol container</summary>
		[System.Xml.Serialization.XmlRoot(ElementName = "Protocol", Namespace = OutlookResponseNamespace)]
		public class ProtocolXml
		{
			/// <summary></summary>
			public string Type = null;
			/// <summary></summary>
			public string Server = null;
			/// <summary></summary>
			public string ServerDN = null;
			/// <summary></summary>
			public string ServerVersion = null;
			/// <summary></summary>
			public string MdbDN = null;
			/// <summary></summary>
			public string ASUrl = null;
			/// <summary></summary>
			public string OOFUrl = null;
			/// <summary></summary>
			public string OABUrl = null;
			/// <summary></summary>
			public string UMUrl = null;
			/// <summary></summary>
			public int Port = 0;
			/// <summary></summary>
			public int DirectoryPort = 0;
			/// <summary></summary>
			public int ReferralPort = 0;
			/// <summary></summary>
			public string FBPublish = null;
			/// <summary></summary>
			public string SSL = null;
			/// <summary></summary>
			public string TTL = null;
			/// <summary></summary>
			public string AuthPackage = null;
			/// <summary></summary>
			public string CertPrincipalName = null;
			/// <summary></summary>
			[System.Xml.Serialization.XmlAnyElement]
			public object[] OtherXml = null;
		}

		/// <summary></summary>
		[System.Xml.Serialization.XmlRoot(ElementName = "Response", Namespace = AutodiscoverResponseNamespace)]
		public class ErrorResponseXml
		{
			/// <summary></summary>
			public ErrorXml Error = null;
		}

		/// <summary>Error container</summary>
		[System.Xml.Serialization.XmlRoot(ElementName = "Error", Namespace = AutodiscoverResponseNamespace)]
		public class ErrorXml
		{
			/// <summary></summary>
			[System.Xml.Serialization.XmlAttribute]
			public string Time = null;
			/// <summary></summary>
			[System.Xml.Serialization.XmlAttribute]
			public string Id = null;
			/// <summary></summary>
			public string ErrorCode = null;
			/// <summary></summary>
			public string Message = null;
			/// <summary></summary>
			public string DebugData = null;
		}
		#endregion

		/// <summary>
		/// Returns local computer's site name.
		/// </summary>
		/// <returns>Name of the local site.</returns>

		

	}
}
